﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using FeatureModelCore;
using TreeGraphicalControl;
using Collections.TreeCollections;
using FeatureModelTool.FeatureModelGraphical.GraphicalControls;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using FeatureModelCore.FMShapes;
using FeatureModelTool.FMAlgorithms;
using Collections;
using FeatureModel.Collections.TreeArgs;
using FeatureModelCore.FMCrossTreeConstraint;
using EventLogAssembly;
using FeatureModelCore.FMInterface;

namespace FeatureModelTool.FeatureModelGraphical
{
    public class FeatureModelGraphicalView : Canvas
    {
        public static readonly int DEFAULT_THICKNESS = 1;
        public static readonly int FOCUS_THICKNESS = 2;


        #region Properties
        public FeatureModelTree TreeInstance
        {
            get
            {
                if (_versionController == null) return null;
                return (FeatureModelTree)this._versionController.CurrentTree;
            }
        }
        #endregion

        #region Fields
        /// <summary>
        /// Feature Model Tree
        /// </summary>
        private TreeVersionController _versionController;
        private List<IControl> _allControls;
        private Grid _grid;
        #endregion

        #region Constructor
        /// <summary>
        /// Constructor
        /// </summary>
        public FeatureModelGraphicalView()
        {
            _versionController = null;
            _allControls = null;  

            _grid = new Grid();
            _grid.Margin = new Thickness(0, 0, 0, 0);
            _grid.Background = Brushes.Azure;
            _grid.MouseLeftButtonDown += new MouseButtonEventHandler(MouseLeftClickDown);

            this.SizeChanged += new SizeChangedEventHandler(View_SizeChanged);
        }
        #endregion
        /// <summary>
        /// Bind Feature Model Tree
        /// </summary>
        /// <param name="fmTree"></param>
        public bool Bind(FeatureModelTree fmTree)
        {
            if(this._versionController != null)
            {
                return false;
            }
            _versionController = new TreeVersionController(fmTree);
            _allControls = new List<IControl>();

            // bind all objects in the feature model into controls
            foreach (TreeObject treeObj in fmTree.AllTreeObjects)
            {
                if (treeObj is FeatureTreeRoot)
                {
                    _allControls.Add(new Control_TreeNode(this, (FeatureTreeRoot)treeObj));
                }
                else if (treeObj is FeatureTreeGroupRelationship)
                {
                    _allControls.Add(new Control_GroupRelationship(this, (FeatureTreeGroupRelationship)treeObj));
                }
                else if (treeObj is FeatureTreeNode)
                {
                    _allControls.Add(new Control_TreeNode(this, (FeatureTreeNode)treeObj));
                }
            }
            foreach (CrossTreeConstraint cons in fmTree.AllCrossTreeConstraints)
            {
                _allControls.Add(new Control_Constraint(this, cons));
            }

            TreeRefreshEventHandler rd = this.Refresh;
            fmTree.TreeModifyCompleted.AddHandler((sender, args) =>
                {
                    this.Dispatcher.BeginInvoke(rd, sender, args);
                });
            Refresh(this, null);
            return true;
        }
        /// <summary>
        /// Refresh
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Refresh(Object sender, TreeEventArgs e)
        {
            if (e != null)
            {
                return;
            }

            if (_versionController == null
                || _allControls == null)
            {
                return;
            }

            // clear
            this.Children.Clear();

            // add grid
            this.Children.Add(_grid);

            // add icon
            Image icon = MainWindow.LoadIcon("/FeatureModelTool;component/Images/featureModelGraphical.png");
            icon.Margin = new Thickness(12, 12, 0, 0);
            icon.Width = 252;
            icon.Height = 90;
            this.Children.Add(icon);

            foreach (IControl control in _allControls)
            {
                UIElement[] newUIs = control.ToUIElement();
                if (newUIs == null)
                {
                    continue;  
                }
                foreach (UIElement ui in newUIs)
                {
                    this.Children.Add(ui);
                }
            }

            //setCanvasSize();
        }
        /// <summary>
        /// Refresh Position
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void RefreshPosition(object sender, EventArgs e)
        {
            setCanvasSize();

            foreach (IControl control in _allControls)
            {
                control.RefreshPosition();
            }
            
        }

        private void setCanvasSize()
        {
            if(TreeInstance == null
                || this.ActualWidth == 0 || this.ActualHeight == 0)
            {
                return;
            }
            FeatureTreeRoot root =(FeatureTreeRoot)TreeInstance.Root;
            List<FMRectangle> rectList = new List<FMRectangle>();
            List<FMCircle> cirList = new List<FMCircle>();

            rectList.Add(root.Shape);
            foreach (IFeature node in TreeInstance.AllFeatureNodes)
            {
                rectList.Add(node.Shape);
            }
            foreach (FeatureTreeGroupRelationship gr in TreeInstance.AllGroupRelationships)
            {
                cirList.Add(gr.Shape);
            }

            double tmpWidth, tmpHeight;
            ConstraintGraphicalAlgorithm.ResetCanvasSize(out tmpWidth, out tmpHeight, rectList.ToArray<FMRectangle>(), cirList.ToArray<FMCircle>());
            if (this.ActualHeight > tmpHeight)
            {
                tmpHeight = this.ActualHeight;
            }
            if (this.ActualWidth > tmpWidth)
            {
                tmpWidth = this.ActualWidth;
            }

            this.Width = tmpWidth;
            this.Height = tmpHeight;
            this._grid.Width = tmpWidth;
            this._grid.Height = tmpHeight;
        }

        /// <summary>
        /// Clear Focus of all UIElement
        /// </summary>
        public void ClearFocus()
        {
            foreach (IControl control in _allControls)
            {
                control.ClearFocus();
            }
        }

        #region Mouse Event Handler
        /// <summary>
        /// Mouse Left Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public void MouseLeftClickDown(object sender, MouseButtonEventArgs args)
        {
            this.ClearFocus();
            this.Refresh(this, null);
        }
        #endregion

        private void View_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            FeatureModelGraphicalView view = sender as FeatureModelGraphicalView;
            if (view == null)
            {
                return;
            }

            //double width = view.ActualWidth;
            //double height = view.ActualHeight;

            //view._grid.Height = height;
            //view._grid.Width = width;

            setCanvasSize();
        }
    }
}
